package com.hockeo.client.ui.base;

import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.google.gwt.user.client.Window;
import com.hockeo.client.model.JSData;

/**
 * Special menu subclass intended to be used for grid context menus. This class
 * automatically registers itself as context menu for the given grid and makes sure that
 * the menu is not shown on the grid header.
 *
 * @version $Id$
 * @author jjanke
 */
public class VHGridContextMenu extends Menu implements Listener<GridEvent<JSData>>
{
  private JSData                             d_modelLastClicked;
  private final SelectionListener<MenuEvent> d_selectionListener = new SelectionListener<MenuEvent>() {

                                                                   @Override
                                                                   public void componentSelected( MenuEvent evt )
                                                                   {
                                                                     MenuItem mi = (MenuItem) evt.getItem();
                                                                     VHGridContextMenu.this.menuItemSelected( mi );
                                                                   }
                                                                 };

  /**
   * Creates a new context menu for the given grid.
   *
   * @param grid the grid to which to attach the context menu
   */
  public VHGridContextMenu( Grid<JSData> grid )
  {
    super();

    grid.addListener( Events.ContextMenu, this );
    grid.setContextMenu( this );
  }

  /**
   * Handles grid events having the type {@link Events#ContextMenu}. Suppresses the
   * context menu if no model is available (i.e. if the right click occured on the grid
   * header). It also saves the model so that it can be used later within the actions of
   * the menu items.
   *
   * @see Listener#handleEvent(com.extjs.gxt.ui.client.event.BaseEvent)
   */
  public void handleEvent( GridEvent<JSData> evt )
  {
    // Only handle context menu events
    //
    if ( !evt.getType().equals( Events.ContextMenu ) )
      return;

    // If there is no model available cancel showing the context menu
    //
    if ( evt.getModel() == null )
    {
      evt.setCancelled( true );
      return;
    }

    d_modelLastClicked = evt.getModel();
    customizeMenuBeforeShowing( d_modelLastClicked );
  }

  /**
   * This method is called just before displaying the context menu to the user. It should
   * be overridden by sub classes. By default, this method does nothing.
   *
   * @param modelLastClicked the model for which the context menu is shown.
   */
  protected void customizeMenuBeforeShowing( JSData modelLastClicked )
  {}

  /**
   * Returns the default selection listener that can be attached to menu items. If a menu
   * item is clicked that is linked to the default selection listener, the method
   * {@link #menuItemSelected(MenuEvent)} will be called.
   */
  protected SelectionListener<MenuEvent> getDefaultSelectionListener()
  {
    return d_selectionListener;
  }

  /**
   * This method is called every time a menu item that is attached to the default menu
   * selection listener ({@link #getDefaultSelectionListener()} is clicked. Please
   * override this method for specific handling routines. By default this method just
   * displays an alert window with the name of the clicked menu item.
   *
   * @param mi the clicked menu item
   */
  protected void menuItemSelected( MenuItem mi )
  {
    Window.alert( "Click on menu item '" + mi.getText() + "' is not handled." );
  }

  /**
   * Returns the model for which the context is currently shown.
   */
  protected JSData getModelLastClicked()
  {
    return d_modelLastClicked;
  }
}
